<template>
  <el-dialog
      :visible.sync="state.dialogVisible"
      :title="state.title"
      align-center
      destroy-on-close
      :width="state.width"
      v-loading="state.loading"
      :close-on-click-modal="false"
  >
    <el-scrollbar :max-height="state.maxHeight" style="padding-right: 10px">
      <avue-form v-if="state.type == '0'" :key="state.key" ref="formRef" :option="form"
                 v-model="formData"></avue-form>
    </el-scrollbar>
    <template #footer>
      <el-button @click="state.dialogVisible = false;">取 消</el-button>
      <el-button type="primary" :loading="state.loading" @click="doSave">保 存</el-button>
    </template>
  </el-dialog>
</template>
<script>
import { setArrayObjectKeyValue } from "@/utils/object";
import { get, post, put } from "@/utils/http/httpUtils";
import { handleTree } from "@/utils/tree";
import { initDictTable } from "@/api/dist";
import { mapGetters, mapActions } from 'vuex';
import {error} from "@/utils/msg";

function replaceDollarBraces(str) {
  return str.toString().replace(/\$\{?([^{}]+)\}?/g, function (match, innerContent) {
    return innerContent ? `'${innerContent}'` : match;
  });
}

function parseJson(column) {
  let attrs = column.attrs;
  if (attrs) {
    try {
      attrs = JSON.parse(attrs)
      for (let key of Object.keys(attrs)) {
        column[key] = attrs[key];
      }
    } catch (e) {
      console.error("解析attrs异常", attrs)
    }
  }
}

export default {
  name: "olForm",
  inject: ['http'],
  data() {
    return {
      formData: {},
      optionData: {},
      form: {
        column: []
      },
      state: {
        loading: false,
        fullscreen: false,
        dialogVisible: false,
        title: "",
        width: '60%',
        comCommit: true,
        maxHeight: '400px',
        type: '0',
        edit: false,
        saveUrl: '',
        requestType: 'post',
        updateKey: '',
        theme: 't1',
        tableConfigId: '',
      },
    }
  },
  computed: {
    ...mapGetters('dict', ['val']),
    ...mapGetters('dictType', {dictTypeVal: 'val'})
  },
  methods: {
    ...mapActions('dict', {dictInit: 'init'}),
    hideColumn(prop) {
      setArrayObjectKeyValue(this.form.column, 'display', false, prop)
    },
    showColumn(prop) {
      setArrayObjectKeyValue(this.form.column, 'display', true, prop)
    },
    getParams() {
      let params = {
        tableConfigId: this.state.tableConfigId,
        columnAndValueMap: {},
      };
      if (this.state.type != '0') {
        let formData = this.$refs.value.getFormData(false);
        for (let prop of Object.keys(formData)) {
          let value = formData[prop];
          if (value instanceof String) {
            value = value.trim();
          }
          params.columnAndValueMap[prop] = value;
        }
      } else {
        for (let {prop} of this.form.column) {
          let value = this.formData[prop];
          if (value) {
            if (value instanceof String) {
              value = value.trim();
            }
            params.columnAndValueMap[prop] = value;
          }
        }
      }
      if (this.state.saveUrl) {
        return params.columnAndValueMap;
      }
      if (this.state.edit) {
        params.whereMap = {}
        if (this.state.updateKey) {
          let split = this.state.updateKey.split(',');
          for (let kv of split) {
            let kvs = kv.split("=");
            if (kvs.length == 2) {
              params.whereMap[kvs[0]] = params.columnAndValueMap[kvs[1]]
              delete params.columnAndValueMap[kvs[0]];
            } else {
              let val = params.columnAndValueMap[kvs];
              params.whereMap[kvs] = val != undefined ? val : this.formData[kvs];
              delete params.columnAndValueMap[kvs];
            }
          }
        } else {
          // 编辑时默认更新条件为id
          params.whereMap['id'] = this.formData['id'];
          if (!params.whereMap['id']) {
            params.whereMap['id'] = this.formData['t1_id'];
          }
          delete params.columnAndValueMap['id'];
        }
      }
      return params
    },
    async doValidate() {
      let dom = undefined;
      let keys = [];
      let status = true;
      if (this.state.type != '0') {
        await this.$refs.formRef.getNativeForm().validate((valid, msg) => {
          if (!valid) {
            keys = Object.keys(msg);
            dom = this.$refs.formRef.getWidgetRef(keys[0]);
            status = false;
          }
        })
      } else {
        await this.$refs.formRef.validate((valid, done, msg) => {
          if (!valid) {
            keys = Object.keys(msg);
            dom = this.$refs.formRef.getPropRef(keys[0]);
            status = false;
          }
          done()
        })
      }
      if (dom) {
        // 定位代码
        dom.$el.scrollIntoView({
          block: "center",
          behavior: "smooth",
        });
        error("您还有" + keys.length + "项信息未填写，请填写后再操作！");
        status = false;
      }
      return status
    },
    async doSave() {
      let validate = await this.doValidate();
      if (!validate) {
        return
      }
      this.state.loading = true;
      try {
        let params = this.getParams()
        let url = this.state.saveUrl ? this.state.saveUrl : this.state.edit ? '/online/crud/modify' : '/online/crud/save'
        if (this.state.requestType.toLowerCase() == "put") {
          await put(this.http, url, params).then(status => {
            this.state.loading = false;
            if (status) {
              this.state.dialogVisible = false;
              this.$emit('query')
            }
          })
        } else {
          await post(this.http, url, params).then(status => {
            this.state.loading = false;
            if (status) {
              this.state.dialogVisible = false;
              this.$emit('query')
            }
          })
        }
      } catch (e) {
        console.error(e)
      } finally {
        this.state.loading = false;
      }

    },
    init(data) {
      if (data.saveUrl) {
        this.state.saveUrl = data.saveUrl.trim();
        if (data.requestType) {
          this.state.requestType = data.requestType;
        }
      }
      this.state.edit = data['code'] == 'edit' == true;
      this.state.title = data.title ? data.title : this.state.edit ? '编辑' : '新增';
      //赋值弹窗宽度和高度
      if (data.form.diaLogWidth) {
        this.state.width = data.form.diaLogWidth
      }
      if (data.form.diaLogHeight) {
        this.state.maxHeight = data.form.diaLogHeight + 'px'
      }
      if (data.form.title) {
        this.state.title = data.form.title
      }
      this.state.dialogVisible = true;
      this.form = data.form;
      this.formData = data.formData;
      for (let key of Object.keys(this.state)) {
        if (data[key]) {
          this.state[key] = data[key]
        }
      }
      if (this.state.type == 0) {
        for (let column of this.form.column) {
          if (column.disabled == 1) {
            column.disabled = true;
          }
          this.initDict(column);
          parseJson(column);
          for (let event of ['change']) {
            if (column[event] && !(column[event] instanceof Function)) {
              try {
                column[event] = eval("(params)=>{this.$nextTick(()=>{" +
                    "let formData = this.formData;console.log(formData);" +
                    "let {value} = params;" + replaceDollarBraces(column[event]) +
                    "})" +
                    "}")
              } catch (e) {
                console.error(e)
              }
            }
          }
        }
      }
    },
    initDict(column) {
      if (column.dictCode) {
        column.dicData = this.val(column.dictCode)
        if (column.selectDom == 1) {
          column.type = "select";
        }
        if (this.state.edit) {
          return;
        }
        if (column.value != undefined) {
          this.formData[column.prop] = String(column.value)
        } else {
          //”number”、”string”、”boolean”、”object”、”function” 和 “undefined”
          let dataType = typeof (this.formData[column.prop]);
          // 数据字典与值类型不一致
          if (this.formData[column.prop] != undefined && this.formData[column.prop] != '' && ["number", "boolean"].indexOf(dataType) != -1) {
            this.formData[column.prop] = String(this.formData[column.prop])
            column.value = this.formData[column.prop];
          } else if (this.formData[column.prop] == undefined) {
            setTimeout(() => {
              if (column.dicData) {
                for (let dicDatum of column.dicData) {
                  if (dicDatum.isDefault == 1) {
                    this.formData[column.prop] = dicDatum.value;
                    column.value = this.formData[column.prop];
                  }
                }
              }
            }, 100)
          }
        }
      } else if (column.dictTable || column.dictUrl) {
        if (column.selectDom == 1) {
          column.type = "select";
        }
        column.filterable = true;
        column.dicData = [];
        setTimeout(() => {
          this.setDictTable(column, undefined);
        }, 10)
        if (column.type == 'tree') {
          column.filterable = column.filterable == undefined ? true : column.clearable;
          column.clearable = column.clearable == undefined ? true : column.clearable;
        } else {
          column.filterMethod = (e) => {
            this.$nextTick(() => {
              this.setDictTable(column, e);
            })
          };
        }
      }
    },
    setDictUrl(column, like) {
      let dictUrl = column.dictUrl.split(",");
      let url;
      let label = 'label';
      let value = 'value';
      let parentId = 'parentId';
      // get,url,label,value,parent_id
      let doGet = true;
      if (dictUrl.length > 1
      ) {
        if (dictUrl[0].toString().toLowerCase() == 'post') {
          doGet = false;
        }
        url = dictUrl[1];
        label = dictUrl[2];
        value = dictUrl[3];
        parentId = dictUrl[4];
      } else {
        url = dictUrl[0];
      }

      if (doGet) {
        get(this.http, url + "?label=" + like).then((data) => {
          column.dicData.length = 0;
          if (column.type == 'tree') {
            for (let da of data) {
              da['label'] = da[label]
              da['value'] = da[value]
            }
            column.dicData = handleTree(data, value, parentId);
          } else {
            data.forEach((d) => {
              column.dicData.push(d);
            })
          }
        })
      } else {
        let params = {}
        if (like) {
          params['label'] = like;
        }
        post(this.http, column.dictUrl, params, false).then(({data}) => {
          column.dicData.length = 0;
          if (column.type == 'tree') {
            for (let da of data) {
              da['label'] = da[label]
              da['value'] = da[value]
            }
            column.dicData = handleTree(data, value, parentId);
          } else {
            data.forEach((da => {
              da['label'] = da[label];
              da['value'] = da[value];
              column.dicData.push(da);
            }))
          }
        })
      }
    },
    setDictTable(column, like) {
      if (column.dictTable && column.dictTable.toString().trim() != '') {
        this.doSetDictTable(column, like);
      } else if (column.dictUrl) {
        this.setDictUrl(column, like);
      }
    },
    doSetDictTable(column, like) {
      let value = this.formData[column.prop];
      /*String tableName;
      String dataBase;
      String label;
      String value;
      Map<String, Object> where;*/
      // olp-vue-pro,system_users,nickname,id,parentId
      let params = {}
      let dictTable = JSON.parse(JSON.stringify(column.dictTable));
      if (dictTable instanceof Object) {
        params = dictTable;
      } else {
        dictTable = column.dictTable.split(",");
        params["dbName"] = dictTable[0];
        params["tableName"] = dictTable[1];
        params["label"] = dictTable[2];
        params["value"] = dictTable[3];
        if (dictTable[4]) {
          params["parentValue"] = dictTable[4];
        }
      }

      if (like || value) {
        if (!params.where) {
          params.where = {};
        }

      }
      if (!params["parentValue"]) {
        if (like) {
          params.where['_like_' + params["label"]] = like;
        }
        if (value) {
          params.defaultValue = value;
        }
      }

      initDictTable(this.http, params).then((data) => {
        column.dicData.length = 0;
        if (params["parentValue"]) {
          column.dicData = handleTree(data, 'dictValue', 'parentValue');
        } else {
          data.forEach((d) => {
            column.dicData.push(d);
          })
        }
      })
    },
    mounted() {
      this.$nextTick(() => {
        this.dictInit(this.http);
      })
    },
  }
}
</script>
